{
  stdenv,
  lib,
  fetchFromGitLab,
  fetchpatch,
  buildPackages,
  gettext,
  pkg-config,
  python3,
  avahi,
  libgphoto2,
  libieee1284,
  libjpeg,
  libpng,
  libtiff,
  libusb1,
  libv4l,
  net-snmp,
  curl,
  systemdLibs,
  withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemdLibs,
  libxml2,
  poppler,
  gawk,
  sane-drivers,
  nixosTests,
  autoconf,
  automake,
  libtool,
  autoconf-archive,

  # List of { src name backend } attribute sets - see installFirmware below:
  extraFirmware ? [ ],

  # For backwards compatibility with older setups; use extraFirmware instead:
  gt68xxFirmware ? null,
  snapscanFirmware ? null,

  # Not included by default, scan snap drivers require fetching of unfree binaries.
  scanSnapDriversUnfree ? false,
  scanSnapDriversPackage ? sane-drivers.epjitsu,
}:

stdenv.mkDerivation (finalAttrs: {
  pname = "sane-backends";
  version = "1.4.0";

  src = fetchFromGitLab {
    owner = "sane-project";
    repo = "backends";
    tag = finalAttrs.version;
    hash = "sha256-e7Wjda+CobYatblvVCGkMAO2aWrdSCp7q+qIEGnGDCY=";
  };

  # Fix hangs in tests, hopefully
  # FIXME: remove in next release
  patches = [
    (fetchpatch {
      url = "https://gitlab.com/sane-project/backends/-/commit/8acc267d5f4049d8438456821137ae56e91baea9.patch";
      hash = "sha256-IyupDeH1MPvEBnGaUzBbCu106Gp7zXxlPGFAaiiINQI=";
    })
  ];

  postPatch = ''
    # Do not create lock dir in install phase
    sed -i '/^install-lockpath:/!b;n;c\       # pass' backend/Makefile.am
  '';

  preConfigure = ''
    # create version files, so that autotools macros can use them:
    # https://gitlab.com/sane-project/backends/-/issues/440
    printf "%s\n" "$version" > .tarball-version
    printf "%s\n" "$version" > .version

    autoreconf -fiv

    # Fixes for cross compilation
    # https://github.com/NixOS/nixpkgs/issues/308283

    # sane-desc will be used in postInstall so compile it for build
    # https://github.com/void-linux/void-packages/blob/master/srcpkgs/sane/patches/sane-desc-cross.patch
    patch -p1 -i ${./sane-desc-cross.patch}
  '';

  outputs = [
    "out"
    "doc"
    "man"
  ];

  depsBuildBuild = [ buildPackages.stdenv.cc ];

  nativeBuildInputs = [
    autoconf
    autoconf-archive
    automake
    gettext
    libtool
    pkg-config
    python3
  ];

  buildInputs = [
    avahi
    libgphoto2
    libjpeg
    libpng
    libtiff
    libusb1
    curl
    libxml2
    poppler
    gawk
  ]
  ++ lib.optionals stdenv.hostPlatform.isLinux [
    libieee1284
    libv4l
    net-snmp
  ]
  ++ lib.optionals withSystemd [
    systemdLibs
  ];

  enableParallelBuilding = true;

  configureFlags = [
    "--with-lockdir=/var/lock/sane"
  ]
  ++ lib.optionals (avahi != null) [ "--with-avahi" ]
  ++ lib.optionals (libusb1 != null) [ "--with-usb" ];

  # autoconf check for HAVE_MMAP is never set on cross compilation.
  # The pieusb backend fails compilation if HAVE_MMAP is not set.
  buildFlags = lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
    "CFLAGS=-DHAVE_MMAP=${if stdenv.hostPlatform.isLinux then "1" else "0"}"
  ];

  postInstall =
    let
      compatFirmware =
        extraFirmware
        ++ lib.optional (gt68xxFirmware != null) {
          src = gt68xxFirmware.fw;
          inherit (gt68xxFirmware) name;
          backend = "gt68xx";
        }
        ++ lib.optional (snapscanFirmware != null) {
          src = snapscanFirmware;
          name = "your-firmwarefile.bin";
          backend = "snapscan";
        };

      installFirmware = f: ''
        mkdir -p $out/share/sane/${f.backend}
        ln -sv ${f.src} $out/share/sane/${f.backend}/${f.name}
      '';
    in
    ''
      mkdir -p $out/etc/udev/rules.d/ $out/etc/udev/hwdb.d
      ./tools/sane-desc -m udev+hwdb -s doc/descriptions:doc/descriptions-external > $out/etc/udev/rules.d/49-libsane.rules
      ./tools/sane-desc -m udev+hwdb -s doc/descriptions:doc/descriptions-external -m hwdb > $out/etc/udev/hwdb.d/20-sane.hwdb

      # net.conf conflicts with the file generated by the nixos module
      rm $out/etc/sane.d/net.conf

    ''
    + lib.optionalString scanSnapDriversUnfree ''
      # the ScanSnap drivers live under the epjitsu subdirectory, which was already created by the build but is empty.
      rmdir $out/share/sane/epjitsu
      ln -svT ${scanSnapDriversPackage} $out/share/sane/epjitsu
    ''
    + lib.concatStrings (map installFirmware compatFirmware);

  # parallel install creates a bad symlink at $out/lib/sane/libsane.so.1 which prevents finding plugins
  # https://github.com/NixOS/nixpkgs/issues/224569
  enableParallelInstalling = false;

  doInstallCheck = true;

  passthru.tests = {
    inherit (nixosTests) sane;
  };

  meta = {
    description = "SANE (Scanner Access Now Easy) backends";
    longDescription = ''
      Collection of open-source SANE backends (device drivers).
      SANE is a universal scanner interface providing standardized access to
      any raster image scanner hardware: flatbed scanners, hand-held scanners,
      video- and still-cameras, frame-grabbers, etc. For a list of supported
      scanners, see http://www.sane-project.org/sane-backends.html.
    '';
    homepage = "http://www.sane-project.org/";
    license = lib.licenses.gpl2Plus;
    platforms = lib.platforms.linux ++ lib.platforms.darwin;
    maintainers = [ lib.maintainers.symphorien ];
  };
})
